import urllib.request   # 网络请求模块
import re   # 正则表达式模块
import sqlite3      # 数据库模块
from selenium import webdriver  # 驱动模块（获取隐藏的html代码）
from selenium.webdriver.chrome.service import Service  

class MySpider:
    def openDB(self):
        # 建立数据库连接（没有该数据库会自动创建）
        self.conn = sqlite3.connect('spider.db')
        self.cursor = self.conn.cursor()
        # 如果有rates表就删除
        try:
            self.cursor.execute("drop table rates")
        except:
            pass
        # execute执行sql语句创建数据表
        sql = "CREATE TABLE IF NOT EXISTS rates (Currency varchar(256) PRIMARY KEY,TSP float,CSP float, TBP float,CBP float,Time varchar(256))"
        self.cursor.execute(sql)

    def closeDB(self):
        # 关闭连接
        self.conn.commit()
        self.conn.close()

    def insertDB(self, Currency, TSP, CSP, TBP, CBP, Time):
        # 插入数据
        try:
            sql = "INSERT INTO rates (Currency,TSP,CSP,TBP,CBP,Time) VALUES (?,?,?,?,?,?)"
            self.cursor.execute(sql, (Currency, TSP, CSP, TBP, CBP, Time))
        except Exception as e:
            print(e)

    def show(self):
        # 显示数据（在终端输出）
        self.cursor.execute("SELECT Currency,TSP,CSP,TBP,CBP,Time FROM rates")
        rows = self.cursor.fetchall()
        # 格式化控制输出表头
        print("%-18s%-12s%-12s%-12s%-12s%-12s" % ("Currency", "TSP", "CSP", "TBP", "CBP", "Time"))
        for row in rows:
            # 格式化控制输出每一行
            print("%-18s%-12s%-12s%-12s%-12s%-12s" % (row[0], row[1], row[2], row[3], row[4], row[5]))

    def match(self, t, s):
        # 匹配函数
        m = re.search(r"<" + t, s)
        if m:
            a = m.start()
            m = re.search(r">", s[a:])
            if m:
                b = a + m.end()
                # 返回一个字典，包含start和end两个键值
                return {"start": a, "end": b}
        return {"start": -1, "end": -1}  # 返回一个无效的结果


    def spider(self,url):
        # 爬虫函数
        try:
            # 指定Microsoft Edge浏览器的WebDriver路径
            service = Service(r"D:\ctf_web_tools\msedgedriver.exe") 

            # 创建Microsoft Edge浏览器的WebDriver
            driver = webdriver.Edge(service=service)

            # 使用WebDriver打开网页
            driver.get(url)
        
            # 获取隐藏的html代码
            html = driver.execute_script('return document.getElementById("root").innerHTML')

            # 取出tbody内元素
            m=re.search(r'<tbody>',html)
            html=html[m.end():]  
            m=re.search(r'</tbody>',html)
            html=html[:m.start()]
            while True:
                # 取出tr内元素
                p=self.match("tr",html)
                q=self.match("/tr",html)
                i=0     # 计数第几个tb
                row=[]      # 存放每一行数据
                if p["start"]!=-1 and q["start"]!=-1:    # 有tr元素
                    # 取出每一个tr内元素
                    tds=html[p["end"]:q["start"]]
                    # 取出每一个td内元素
                    a=self.match("td",tds)
                    b=self.match("/td",tds)
                    while a["start"]!=-1 and b["start"]!=-1:  # 有td元素
                        i+=1
                        # 取出每一个td内元素
                        every=tds[a["end"]:b["start"]]
                        if i==1:                        
                            # 取出span内的currency
                            m=self.match("span",every)
                            n=self.match("/span",every)
                            Currency=every[m["end"]:n["start"]]
                            row.append(Currency)
                        elif i in [4,5,6,7,8]:
                            # 取出td内的数字
                            value=tds[a["end"]:b["start"]]
                            row.append(value)
                        # 删去已取出的元素
                        tds=tds[b["end"]:]
                        # 取出下一个td内元素
                        a=self.match("td",tds)
                        b=self.match("/td",tds)
                    # 存入数据库
                    if len(row)==6:
                        self.insertDB(row[0],row[1],row[2],row[3],row[4],row[5])
                    # 删去已取出的元素
                    html=html[q["end"]:]
                else:
                    break

        except Exception as e:
            print(e)
        
    def process(self):
        # 执行爬虫
        self.openDB()
        self.spider("https://fx.cmbchina.com/hq")
        self.show()
        self.closeDB()

# 主程序
spider=MySpider()
spider.process()
            